package ru.ifmo.genetics.mutation.string;

import org.uncommons.maths.number.NumberGenerator;
import org.uncommons.maths.random.Probability;
import ru.ifmo.automaton.Automaton;
import ru.ifmo.common.Source;
import ru.ifmo.genetics.mutation.AbstractMutation;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;

/**
 * @author Roman Kolganov
 *         16.05.12
 */
public class RemoveUselessCharsMutation extends AbstractMutation<String> {

    private final Source<Automaton<Character, String>> automatonSource;

    public RemoveUselessCharsMutation(NumberGenerator<Probability> mutationProbability,
                                      Source<Automaton<Character, String>> automatonSource) {
        super(mutationProbability);
        this.automatonSource = automatonSource;
    }

    @Override
    protected String mutate(String individual, Random rng) {
        boolean[] useless = new boolean[individual.length()];
        Automaton<Character, String> automaton = automatonSource.create();
        Set<String> QStepPrefix = new HashSet<String>(automaton.getStatesCount());
        for (String state : automaton) {
            QStepPrefix.add(state);
        }
        for (int i = 0; i < individual.length(); i++) {
            Set<String> QStepNextPrefix = new HashSet<String>(automaton.getStatesCount());
            for (String state : QStepPrefix) {
                automaton.goToState(state);
                QStepNextPrefix.add(automaton.step(individual.charAt(i)));
            }
            useless[i] = QStepPrefix.equals(QStepNextPrefix);
            QStepPrefix = QStepNextPrefix;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < individual.length(); i++) {
            if (!useless[i]) {
                sb.append(individual.charAt(i));
            }
        }
        return sb.toString();
    }
}
